<template>
    <canvas class="model-canvas" ref="canvas" />
</template>

<script>
import { fabric as Fabric } from "fabric";
import DesignResource from '@/utils/DesignResource.js';
import DesignEditor from '@/utils/DesignEditor.js';

export default {
    props: {
        model: { require: true, type: Object, default: null },
        color: { require: true, type: Object, default: null },
        pieces: { require: true, type: Array, default () { return [] } },
        activePiece: { require: true, type: Object, default: () => ({}) },

    },
    data () {
        return {
            fabric: null,
            scale: null,
            mask: null,
            editors: [],
            background: null,
        };
    },
    watch: {
        color () { this.init(); },
        model () { this.init(); },
        activePiece: {
            immediate: false,
            deep: true,
            handler (newval, oldval) {
                const piece = newval || {}
                const editor = this.editors.find(e => e.type == piece.type && e.canvas_name == piece.canvas_name)
                editor && editor.renderLayers(piece.layers || [])
            },
        },
    },

    methods: {
        // 绘制区
        getRenderPiece (mapper) {
            let pieces = this.pieces || [];
            let canvas_name = mapper.canvas_name;
            let piece = pieces.filter(i => i.canvas_name == canvas_name)[0];
            return piece;
        },

        // 排序
        updateModelIndex () {

            const model = this.model || {};
            const mapping = this.model.mapping || [];
            const stage = this.fabric.getObjects().slice(0);
            const names = ['-background'].concat(mapping.map(item => [item.type, item.canvas_name].join('-')));

            // 设计置顶
            if (model.mapping_top) {
                names.splice(1, 0, '-mask')
            } else {
                names.push('-mask');
            }
            // 排序
            stage.sort((a, b) => names.indexOf([a.canvas_type, a.canvas_name].join('-')) - names.indexOf([b.canvas_type, b.canvas_name].join('-')))
            stage.map((item, index) => this.fabric.moveTo(item, index));

        },


        // 更新遮罩图片
        updateModelMask () {

            const model = this.model;
            const color = this.color;
            const opt = { type: 'simple', form: 'model' }


            if (!this.background) {
                this.background = new Fabric.Image(null, { originX: 'center', originY: 'center' })
                this.background.canvas_name = 'background';
                this.fabric.add(this.background);
            }

            if (!this.mask) {
                this.mask = new Fabric.Image(null, { originX: 'center', originY: 'center' })
                this.mask.canvas_name = 'mask';
                this.fabric.add(this.mask);
            }

            if (model && model.mask_image && color) {
                const promises = [];

                promises.push(DesignResource.loadImage(model.mask_image, opt));
                const taxture = this.$modelColorTaxture(model, color)
                if (taxture) {
                    promises.push(DesignResource.loadImage(taxture, opt));
                }

                // // 有背景图
                // if (color_url) {
                //     promises.push(DesignResource.loadImage(color_url, opt));
                // }

                Promise.all(promises).then(result => {


                    if (this.model == model && this.color == color) {

                        const modelImg = result[0];
                        const colorImg = result[1];

                        this.mask.setElement(modelImg);
                        this.mask.set({
                            left: this.fabric.width / 2,
                            top: this.fabric.height / 2,
                            width: modelImg.width,
                            height: modelImg.height,
                            scaleX: this.fabric.width / modelImg.width,
                            scaleY: this.fabric.height / modelImg.height,
                            opacity: 1,
                        })

                        if (colorImg) {
                            this.background.setElement(colorImg);
                            this.background.set({
                                left: this.fabric.width / 2,
                                top: this.fabric.height / 2,
                                width: colorImg.width,
                                height: colorImg.height,
                                scaleX: this.fabric.width / colorImg.width,
                                scaleY: this.fabric.height / colorImg.height,
                                opacity: 1,
                                backgroundColor: '',
                            });
                        } else {
                            this.background.setElement(null);
                            this.background.set({
                                left: this.fabric.width / 2,
                                top: this.fabric.height / 2,
                                width: this.fabric.width,
                                height: this.fabric.height,
                                scaleX: 1,
                                scaleY: 1,
                                opacity: 1,
                                backgroundColor: this.$modelBackgroundColor(color.color_num, model),
                            });

                        }

                        this.updateModelIndex();
                        this.fabric.renderAll();
                    }

                }).catch(error => {
                    if (this.model == model && this.color == color) {
                        this.mask.set({ opacity: 0 });
                    }
                });

            } else {
                this.background.set({ opacity: 0 });
                this.mask.set({ opacity: 0 });
            }
        },


        // // 更新设计面
        // updateMapping () {

        // 	const mapping = this.model.mapping || []
        // 	const piecesObject = Object.fromEntries(this.pieces.map((i) => [i.canvas_name, i]));

        // 	this.mapping = mapping.map(mapper => {
        // 		const piece = piecesObject[mapper.canvas_name];
        // 		const option = {
        // 			canvas_name: piece.canvas_name,
        // 			canvas_scale: this.scale,
        // 			canvas_model: "simple",
        // 			canvas_width: piece.canvas_width,
        // 			canvas_height: piece.canvas_height,
        // 			design_layers: [],
        // 		};
        // 		const editor = new DesignEditor(Fabric, null, option);
        // 		return {
        // 			elem: editor.fabric.lowerCanvasEl,
        // 			editor: editor,
        // 			canvas_name: piece.canvas_name,
        // 			piece: piece,
        // 			pieceCache: '',
        // 			status: '',
        // 			change: false,
        // 		};
        // 	})
        // },

        // 更新模特的所有设计面
        updateModelPieces () {

            // 删除原来的所有stage
            const mapping = (this.model || {}).mapping || [];
            const piecesObject = new Map(this.pieces.map(i => [[i.type, i.canvas_name].join('-'), i]));
            const piecesMapping = mapping.map(i => piecesObject.get([i.type, i.canvas_name].join('-')));
            const editors = []


            // console.log(mapper.type, mapper.canvas_name);


            piecesMapping.map(mapper => {
                const piece = mapper ? piecesObject.get([mapper.type, mapper.canvas_name].join('-')) : null;

                // 空值不用管
                if (piece) {

                    let option = {
                        type: piece.type,
                        canvas_name: piece.canvas_name,
                        canvas_scale: this.scale,
                        canvas_model: "simple",
                        canvas_width: piece.canvas_width,
                        canvas_height: piece.canvas_height,
                        design_layers: [],
                        onUpdate: (fabric) => {

                            const state = {
                                type: piece.type,
                                canvas_name: piece.canvas_name,
                                canvas: fabric.lowerCanvasEl,
                                fabric: fabric,
                                // layers: piece.layers.slice(0),
                            };
                            //  触发更新
                            this.updatePieceStage(state);
                        },
                    };

                    let editor = new DesignEditor(Fabric, null, option);

                    editor.renderLayers(piece.layers || [])
                    editors.push(editor);
                }
            });

            this.editors = editors;
        },


        updatePieceStage (state = {}) {

            // 要做节流处理，防止计算量过大会爆炸
            // 这里应该直接从layer数据中处理，
            // this.render && this.render.exportImage()
            // this.render && this.render.updateMapper(event)


            const model = this.model || {}
            const mapping = model.mapping || []
            const mapper = mapping.find(i => i.type == state.type && i.canvas_name == state.canvas_name);



            if (!mapper) {
                // 不在这个区域
            } else if (!this.fabric) {
                // 没有初始化
            } else {

                const canvas = state.canvas;
                const cache = this.fabric.getObjects().find(s => s.canvas_type == mapper.type && s.canvas_name == mapper.canvas_name);
                const option = {
                    left: this.scale * (mapper.x + 0.5 * mapper.width),
                    top: this.scale * (mapper.y + 0.5 * mapper.height),
                    width: canvas.width,
                    height: canvas.height,
                    scaleX: this.scale * mapper.width / canvas.width,
                    scaleY: this.scale * mapper.height / canvas.height,
                    angle: mapper.rotate,
                    opacity: 0.95,
                }

                if (cache) {
                    cache.setElement(canvas);
                    cache.set(option);
                    this.fabric.renderAll();
                } else {

                    const stage = new Fabric.Image(canvas, { originX: 'center', originY: 'center' });

                    if (mapper.clip) {
                        option.clipPath = new Fabric.Path(mapper.clip, {
                            absolutePositioned: true,
                            lockScalingX: true,
                            lockScalingY: true,
                            lockMovementX: true,
                            lockMovementY: true,
                            lockSkewingX: true,
                            lockSkewingY: true,
                            originX: 'left',
                            originY: 'top',
                            scaleX: this.scale,
                            scaleY: this.scale,
                            fill: '#f00',
                        })

                        option.clipPath.set({
                            left: option.clipPath.left * this.scale,
                            top: option.clipPath.top * this.scale,
                        })
                    }

                    stage.set(option);
                    stage.canvas_name = mapper.canvas_name;
                    stage.canvas_type = mapper.type;

                    this.fabric.add(stage);
                    this.updateModelIndex();
                    this.fabric.renderAll();

                }
            }
        },

        // 初始化
        init () {
            if (!this.$el) {
                // 没有值
            } else if (!this.model) {
                // 没有设计面
            } else {
                const model = this.model;
                const rect = this.$el.parentNode.getBoundingClientRect();
                const scale = 2 * Math.max(rect.width / model.outer_width, rect.height / model.outer_height);
                const width = scale * model.outer_width || 800;
                const height = scale * model.outer_height || 800;

                this.scale = scale;


                if (this.fabric) {
                    this.fabric.setWidth(width);
                    this.fabric.setHeight(height);
                } else {
                    this.fabric = new Fabric.StaticCanvas(this.$refs.canvas || null, {
                        enableRetinaScaling: false,
                        width: width,
                        height: height,
                    });
                }


                // 清空数据
                this.mask = null;
                this.background = null;
                this.fabric.getObjects().map(stage => this.fabric.remove(stage));


                // 更新背景
                this.updateModelMask();

                // 更新设计面
                this.updateModelPieces();
            }
        },

    },
    mounted () {
        this.init();
        this.$on("global:DESIGN_CLEANUP", () => this.$nextTick(() => this.init()));
    },
    // 销毁
    beforeDestroy () {
        this.fabric && this.fabric.dispose()
    }
};
</script>

<style lang='scss' scoped>
.test {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;

    span {
        position: absolute;
        background: rgba(255, 0, 0, 0.3);
    }
}

.model-panel {
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    height: 100%;
    width: 100%;
    text-align: center;

    img {
        height: 100%;
    }

    button {
        position: absolute;
        width: 24px;
        height: 24px;
        background: none;
        border: none;
        padding: 0;
        top: 50%;
        transform: translateY(-50%);

        &.model-panel-prev {
            left: -36px;
        }

        &.model-panel-next {
            right: -36px;
        }

        &:hover {
            color: #ea4c89;
        }

        &[disabled] {
            color: #ddd;
        }
    }
}

.model-canvas {
    position: absolute;
    left: 0;
    top: 0;
    width: 100% !important;
    height: 100% !important;
}
</style>
